package cn.com.taurus.dispose;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.header.HeaderWriter;
import org.springframework.security.web.header.HeaderWriterFilter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class WebSecurity extends WebSecurityConfigurerAdapter {


    //构造一个内存框架对象，获取数据库中的数据
    @Bean
    public UserDetailsService myUserDetailsService(){
        return new UserSecurityService();
    }
    //明文加密器,只需要在内存中有这个管理对象,如果不添加，从前端登录时会抛出异常
    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }


    /**
     * 通过auth可以在内存中构建虚拟的用户名和密码
     * @param auth
     * @throws Exception
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(myUserDetailsService());
    }

    /**
     * 安全机制拦截
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()// 开启权限控制,通过ANT规范，自定义逻辑
                //通过url授权
                //如果访问/major/*的时候需要拥有admin的权限
//                .antMatchers("/major/*").hasAuthority("admin")
//                .antMatchers("/finance/*").hasAuthority("finance")
//                .antMatchers("/major/*").authenticated()

                //允许/Anonymous/*的所有访问路径匿名通过
                .antMatchers("/Anonymous/*").permitAll()
                .antMatchers("/send/*").permitAll()
                .antMatchers("/sockjs/*").permitAll()
                // 其它请求都需要校验
                .anyRequest().authenticated()

                .and()
                .formLogin()
                .loginPage("/login-view")
                .loginProcessingUrl("/adminsLogin")
                .successForwardUrl("/selectAdminsWeb")
                .permitAll()

                .and()
                //每一个用户登录成功以后会创建一个新的会话
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)

                .and()
                //自定义退出的url
                .logout()
                .logoutUrl("/logout")
                .logoutSuccessUrl("/login-view?logout");
        //跨站请求伪造，限制了除了get以外的大多数方法
        http.csrf().disable();


        //SpringSecurity会屏蔽网页的ifream框架，需要加以下语句
        HeaderWriter headerWriter = new HeaderWriter() {
            @Override
            public void writeHeaders(HttpServletRequest request, HttpServletResponse response) {
                response.setHeader("X-Frame-Options","SAMEORIGIN");
            }
        };
        List<HeaderWriter> headerWriters = new ArrayList<>();
        headerWriters.add(headerWriter);
        HeaderWriterFilter headerWriterFilter = new HeaderWriterFilter(headerWriters);
        http.addFilter(headerWriterFilter);
    }
    /**
     * Spring boot的默认静态资源放置位置是在resource static下，可以在static下新建一个文件夹，然后在上述方法中指定跳过拦截的文件路径即可
     * @param web 参数
     * @throws Exception 异常
     */
    @Override
    public void configure(org.springframework.security.config.annotation.web.builders.WebSecurity web) throws Exception {
        //解决静态资源被拦截的问题
        web.ignoring().antMatchers("/image/**","/img/**","/imager/**","/homepage/**","/automatic/**"
                ,"/css/**","/js/**","/Resource/**","/Resource/css/**","/Resource/echarts/**","/Resource/js/**","/Resource/layui/**");
    }
}
